-------What Makes A Dinosaur Sore------
A 4am crack                  2016-10-21
---------------------------------------

Name: What Makes A Dinosaur Sore
Genre: educational
Year: 1987
Credits: Rob Shaver, Peter Andrews,
  James Morrow, Angela Faeth
Publisher: D.C. Heath and Company
Media: two single-sided 5.25-inch disks
OS: ProDOS 1.2
Previous cracks: none
Similar cracks:
  #811 Rosie The Counting Rabbit
  #202 Squeegee Learns About Drugs
       (spoiler: they're bad, mmkay)

Only disk 1 ("program") is bootable, so
I'll start there.

                   ~

               Chapter 0
 In Which Various Automated Tools Fail
          In Interesting Ways


COPYA
  no read errors, but copy loads ProDOS
  then hangs with drive motor on

Locksmith Fast Disk Backup
  ditto

EDD 4 bit copy (no sync, no count)
  ditto

Copy ][+ nibble editor
  nothing suspicious

Disk Fixer
  T00 -> looks like ProDOS bootloader
  and disk catalog

Why didn't any of my copies work?
  probably a nibble check in the first
  SYSTEM file

Next steps:

  1. trace first .SYSTEM file
  2. disable protection check
  3. I don't know, go feed the ducks or
     something?

                   ~

               Chapter 1
        In Which Things Are Not
         Always As They Appear


[S7,D1=my ProDOS hard drive]
[S6,D1=non-working copy]

]PR#7
]CAT,S6,D1

/EXPLORE

 NAME           TYPE  BLOCKS  MODIFIED

 DISK            BIN       4  24-FEB-88
 FLIPS           DIR       1   3-AUG-87
 ICONS           DIR       1   9-JAN-87
 AUXLOW          BIN       8  24-FEB-88
 AUX.48          BIN      33  24-FEB-88
 AUX.LC          BIN      25  24-FEB-88
 SETUP           BIN       1  24-FEB-88
 STORY.SYSTEM    SYS       3  24-FEB-88
*PRODOS          SYS      32   6-SEP-86
 TITLE.SCREEN    BIN      12   2-SEP-86
 MEMORY.CONFIG   SYS       3  16-DEC-88
 WORDS           DIR       1   9-JAN-87
 P.DINO.3        DIR       1   3-AUG-87
 COLOR.DATA      BIN       7  15-JUL-86

BLOCKS FREE:   83     BLOCKS USED:  197

]PREFIX /EXPLORE
]-STORY.SYSTEM
...loads and runs(!)...

Wait, what?

It's looking more and more likely that
the nibble check is inside the PRODOS
file itself.

Instead of tracing the entire PRODOS
file, I turn to my trusty Disk Fixer
sector editor and searched for the hex
sequence "BD 89 C0". Although there are
many variations of copy protection, a
surprising number of disks use a nibble
check that starts by loading the X
register with the slot number (x16) and
an "LDA $C089,X" instruction to turn on
the drive motor.

And I get lucky: four matches.

 - T00,S0E - part of the ProDOS
   bootloader (expected)

 - T11,S00 - Copy II Plus disk map says
   this is part of the PRODOS file, but
   I looked and it's part of the RWTS.
   So this is expected and legitimate,
   not the start of a nibble check.

 - T0A,S05 - two matches, both highly
   suspicious

Copy II Plus disk map says T0A,S05 is
part of the MEMORY.CONFIG file. It's a
SYS file, which means it's probably
loaded at $2000.

]PR#7
...
]PREFIX /EXPLORE
]BLOAD MEMORY.CONFIG,A$2000,TSYS
]CALL -151

*2000L

2000-   20 D1 21    JSR   $21D1

*21D1L

; set up an MLI call with the boot slot
21D1-   AD 30 BF    LDA   $BF30
21D4-   8D DF 21    STA   $21DF

; call ProDOS MLI with command #$80,
; which is a raw block read
21D7-   20 00 BF    JSR   $BF00
21DA-  [80]
21DB-  [DE 21]
21DD-   60          RTS

Continuing from $2003...

; turn on slot motor manually (always
; suspicious)
2003-   AE 30 BF    LDX   $BF30
2006-   BD 8A C0    LDA   $C08A,X
2009-   BD 89 C0    LDA   $C089,X
200C-   BD 8E C0    LDA   $C08E,X

; an address? ($2300) or two separate
; parameters
200F-   A9 00       LDA   #$00
2011-   85 00       STA   $00
2013-   A9 23       LDA   #$23
2015-   85 01       STA   $01

; not shown, but the subroutine at
; $21E4 moves the drive head to the
; track given in zero page $01
2017-   20 E4 21    JSR   $21E4

So we're on track $23, which is weird.
But wait, it's about to get weirder.

                   ~

               Chapter 2
         A Fish Out Of ProDOS


Continuing from $201A...

201A-   20 36 20    JSR   $2036

*2036L

2036-   A9 00       LDA   #$00
2038-   85 04       STA   $04

; turn on slot motor manually, again,
; because abstractions are difficult
; I guess
203A-   AE 30 BF    LDX   $BF30
203D-   BD 89 C0    LDA   $C089,X
2040-   BD 8E C0    LDA   $C08E,X

2043-   20 74 21    JSR   $2174

*2174L

; boot slot (x16)
2174-   AE 30 BF    LDX   $BF30

; this looks identical to the code in
; a standard DOS 3.3 RWTS (specifically
; at $B944) which finds the next
; available address field
2177-   A0 FC       LDY   #$FC
2179-   84 26       STY   $26
217B-   C8          INY
217C-   D0 04       BNE   $2182
217E-   E6 26       INC   $26
2180-   F0 4D       BEQ   $21CF

; match "D5 AA 96" nibble sequence
2182-   BD 8C C0    LDA   $C08C,X
2185-   10 FB       BPL   $2182
2187-   C9 D5       CMP   #$D5
2189-   D0 F0       BNE   $217B
218B-   EA          NOP
218C-   BD 8C C0    LDA   $C08C,X
218F-   10 FB       BPL   $218C
2191-   C9 AA       CMP   #$AA
2193-   D0 F2       BNE   $2187
2195-   A0 03       LDY   #$03
2197-   BD 8C C0    LDA   $C08C,X
219A-   10 FB       BPL   $2197
219C-   C9 96       CMP   #$96
219E-   D0 E7       BNE   $2187
21A0-   A9 00       LDA   #$00
21A2-   85 27       STA   $27
21A4-   BD 8C C0    LDA   $C08C,X
21A7-   10 FB       BPL   $21A4
21A9-   2A          ROL
21AA-   85 26       STA   $26
21AC-   BD 8C C0    LDA   $C08C,X
21AF-   10 FB       BPL   $21AC
21B1-   25 26       AND   $26

; it even parses the address field into
; the same zero page locations as DOS
21B3-   99 2C 00    STA   $002C,Y
21B6-   45 27       EOR   $27
21B8-   88          DEY
21B9-   10 E7       BPL   $21A2
21BB-   A8          TAY
21BC-   D0 11       BNE   $21CF

; match single #$DE nibble for epilogue
21BE-   BD 8C C0    LDA   $C08C,X
21C1-   10 FB       BPL   $21BE
21C3-   C9 DE       CMP   #$DE
21C5-   D0 08       BNE   $21CF
21C7-   EA          NOP
21C8-   BD 8C C0    LDA   $C08C,X
21CB-   10 FB       BPL   $21C8
21CD-   18          CLC
21CE-   60          RTS
21CF-   38          SEC
21D0-   60          RTS

Continuing from $2046...

; is this the sector we wanted? (the
; physical sector number is now in
; zero page $2D)
2046-   A5 2D       LDA   $2D
2048-   C5 04       CMP   $04

; nope, loop back until we find it
204A-   D0 F7       BNE   $2043

; skip to sync byte (#$FF)
204C-   BD 8E C0    LDA   $C08E,X
204F-   BD 8C C0    LDA   $C08C,X
2052-   10 FB       BPL   $204F
2054-   C9 FF       CMP   #$FF
2056-   D0 F4       BNE   $204C
2058-   A0 00       LDY   #$00
205A-   C8          INY

; skip an exact number of nibbles and
; look for #$D5
205B-   BD 8E C0    LDA   $C08E,X
205E-   BD 8C C0    LDA   $C08C,X
2061-   10 FB       BPL   $205E
2063-   C9 D5       CMP   #$D5

; if not found in correct location (Y
; register counts the nibbles before
; the #$D5), try again from the top
2065-   D0 F3       BNE   $205A
2067-   C0 07       CPY   #$07
2069-   D0 D8       BNE   $2043

; do this for all sectors
206B-   E6 04       INC   $04
206D-   A9 10       LDA   #$10
206F-   C5 04       CMP   $04
2071-   D0 D0       BNE   $2043

; start over on sector 0
2073-   A9 00       LDA   #$00
2075-   85 04       STA   $04
2077-   20 74 21    JSR   $2174
207A-   A5 2D       LDA   $2D
207C-   C5 04       CMP   $04
207E-   D0 F7       BNE   $2077

; skip to address epilogue
2080-   BD 8C C0    LDA   $C08C,X
2083-   10 FB       BPL   $2080
2085-   C9 AA       CMP   #$AA
2087-   D0 F7       BNE   $2080
2089-   BD 8C C0    LDA   $C08C,X
208C-   10 FB       BPL   $2089
208E-   C9 EB       CMP   #$EB
2090-   D0 EE       BNE   $2080

; skip to sync byte (#$FF)
2092-   BD 8C C0    LDA   $C08C,X
2095-   10 FB       BPL   $2092
2097-   C9 FF       CMP   #$FF
2099-   D0 F7       BNE   $2092

; skip an exact number of nibbles and
; look for #$D5
209B-   A0 00       LDY   #$00
209D-   C8          INY
209E-   BD 8E C0    LDA   $C08E,X
20A1-   BD 8C C0    LDA   $C08C,X
20A4-   10 FB       BPL   $20A1
20A6-   C9 D5       CMP   #$D5

; if not found in correct location, try
; again from the top
20A8-   D0 F3       BNE   $209D

; again, Y register counts the nibbles
; before the #$D5
20AA-   C0 10       CPY   #$10
20AC-   D0 C5       BNE   $2073

; do this for several other sectors
20AE-   E6 04       INC   $04
20B0-   A9 0A       LDA   #$0A
20B2-   20 68 21    JSR   $2168
20B5-   A9 04       LDA   #$04
20B7-   C5 04       CMP   $04
20B9-   D0 04       BNE   $20BF
20BB-   E6 04       INC   $04
20BD-   D0 B8       BNE   $2077
20BF-   A9 0F       LDA   #$0F
20C1-   C5 04       CMP   $04
20C3-   D0 BB       BNE   $2080
20C5-   20 74 21    JSR   $2174
20C8-   A5 2D       LDA   $2D
20CA-   C9 0F       CMP   #$0F
20CC-   D0 F7       BNE   $20C5

; read data field (not shown)
20CE-   20 FB 20    JSR   $20FB

; look for #$A5 nibble in a specific
; place
20D1-   A0 00       LDY   #$00
20D3-   C8          INY
20D4-   BD 8E C0    LDA   $C08E,X
20D7-   BD 8C C0    LDA   $C08C,X
20DA-   10 FB       BPL   $20D7
20DC-   C9 A5       CMP   #$A5
20DE-   D0 F3       BNE   $20D3

; Y register counts nibbles before #$A5
20E0-   C0 2D       CPY   #$2D
20E2-   D0 E1       BNE   $20C5

; look for #$D5 nibble in a specific
; place
20E4-   A0 00       LDY   #$00
20E6-   C8          INY
20E7-   BD 8E C0    LDA   $C08E,X
20EA-   BD 8C C0    LDA   $C08C,X
20ED-   10 FB       BPL   $20EA
20EF-   C9 D5       CMP   #$D5
20F1-   D0 F3       BNE   $20E6

; Y register counts nibbles before #$D5
20F3-   C0 5D       CPY   #$5D
20F5-   D0 CE       BNE   $20C5

; success path falls through to here
20F7-   A0 00       LDY   #$00
20F9-   EA          NOP
20FA-   60          RTS

My copy never makes it this far. It's
stuck in an infinite loop, trying to
find a precisely organized track $23
(and failing).

Continuing from $201D...

; seek back to track $00 (from $23)
201D-   A9 23       LDA   #$23
201F-   85 00       STA   $00
2021-   A9 00       LDA   #$00
2023-   85 01       STA   $01
2025-   20 E4 21    JSR   $21E4

; copy some real code to lower memory
2028-   A0 00       LDY   #$00
202A-   B9 42 22    LDA   $2242,Y
202D-   99 00 10    STA   $1000,Y
2030-   C8          INY
2031-   D0 F7       BNE   $202A

; and jump there
2033-   4C 00 10    JMP   $1000

It looks like I should be able to skip
over the protection check by jumping
straight to the success path at $2028.

T18,S00,$00: 202021 -> 4C2820

]PR#6
...works...

Disk 2 ("student disk") is unprotected.

Quod erat liberandum.

                   ~

               Epilogue


The program runs when I execute
STORY.SYSTEM directly. So how does
MEMORY.CONFIG get called?

Disk Fixer
  --> [F]ind
    --> [A]SCII
      --> "CONFIG"

                 --v--

-------------- DISK EDIT --------------
TRACK $0E/SECTOR $0D/VOLUME $FE/BYTE$E8
---------------------------------------
$80: CD A2 A0 C6 C9 CC C5 A0   M" FILE
$88: A0 AA AA A0 AA AA A0 A0    ** **
$90: D3 D9 D3 D4 C5 CD A0 D0   SYSTEM P
$98: D2 CF C7 D2 C1 CD A0 D4   ROGRAM T
$A0: CF CF A0 CC C1 D2 C7 C5   OO LARGE
$A8: A0 A0 AA AA AA AA A0 D5     **** U
$B0: CE C1 C2 CC C5 A0 D4 CF   NABLE TO
$B8: A0 CC CF C1 C4 A0 D8 AE    LOAD X.
$C0: D3 D9 D3 D4 C5 CD A0 AA   SYSTEM *
$C8: AA AA AA AA AA AA AA AA   ********
$D0: AA 00 03 80 02 00 14 01   *@C.B@TA
$D8: 02 01 00 00 00 04 01 00   BA@@@DA@
$E0: 20 00 00 00 00 01 00 AE    @@@@A@.
$E8: C3 CF CE C6 C9 C7 8D 08   CONFIG.H
     ^^^^^^^^^^^^^^^^^
  this should be "SYSTEM"

$F0: C0 B5 42 8D 09 C0 95 42   @5B.I@.B
$F8: CA 10 F3 A9 28 38 8D 08   JPs)(8.H
---------------------------------------
BUFFER 0/SLOT 6/DRIVE 1/MASK OFF/NORMAL

----------------------------------------
COMMAND : _

                 --^--

And there it is: a hacked version of
PRODOS that, instead of looking for the
first .SYSTEM file, looks for the first
.CONFIG file. Of course there's only
one of those, MEMORY.CONFIG, which
silently performs its nibble check
before manually reading STORY.SYSTEM
and jumping to it.

---------------------------------------
A 4am crack                     No. 884
------------------EOF------------------
